home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 March / Macworld (1998-03) (Disk 1).dmg / Shareware World / Info / For Developers / GhostScript 5.10 / MacGS-510 / files / pdf_font.ps < prev    next >
Text File  |  1997-09-12  |  15KB  |  456 lines

  1. %    Copyright (C) 1994, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of Aladdin Ghostscript.
  3. % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  4. % or distributor accepts any responsibility for the consequences of using it,
  5. % or for whether it serves any particular purpose or works at all, unless he
  6. % or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  7. % License (the "License") for full details.
  8. % Every copy of Aladdin Ghostscript must include a copy of the License,
  9. % normally in a plain ASCII text file named PUBLIC.  The License grants you
  10. % the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. % under certain conditions described in the License.  Among other things, the
  12. % License requires that the copyright notice and this notice be preserved on
  13. % all copies.
  14.  
  15. % pdf_font.ps
  16. % PDF font operations.
  17.  
  18. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  19. .currentglobal true .setglobal
  20. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  21. GS_PDF_ProcSet begin
  22. pdfdict begin
  23.  
  24. % We cache the PostScript font in an additional element of the
  25. % font resource dictionary, called PSFont.
  26.  
  27. % ---------------- Encodings ---------------- %
  28.  
  29. % Apply a list of differences to an Encoding.
  30. /updateencoding        % <encoding> <differences> updateencoding <enc'>
  31.  { exch dup length array copy
  32.    exch dup 0 get exch dup length 1 sub
  33.    1 exch getinterval
  34.     { dup type /nametype ne
  35.        { exch pop }
  36.        { 3 copy put pop 1 add }
  37.       ifelse
  38.     }
  39.    forall pop
  40.  } bdef
  41.  
  42. % Get the Encoding for a font.
  43. /getencoding        % <base-encoding> <font-resource> getencoding <enc>
  44.  { /Encoding knownoget
  45.     { dup type /nametype eq
  46.        { exch pop findencoding
  47.        }
  48.        { dup /BaseEncoding knownoget
  49.       { findencoding 3 -1 roll pop exch
  50.       }
  51.      if
  52.      /Differences knownoget { updateencoding } if
  53.        }
  54.       ifelse
  55.     }
  56.    if
  57.  } bdef
  58.  
  59. % Adjust a font according to the Encoding and Widths in the font resource.
  60. /adjustfont        % <font-resource> <font> adjustfont
  61.             %   <font'> <changed>
  62.  { getfontencoding getfontmetrics 4 -1 roll pop .updatefont
  63.     { dup /FontName 2 copy get genfontname dup 5 1 roll put definefont }
  64.    if
  65.  } bind def
  66.  
  67. % Get the (possibly modified) encoding of a font.
  68. /getfontencoding    % <font-resource> <font> getfontencoding
  69.             %   <font-resource> <font> <encoding>
  70.  { dup /Encoding get 2 index getencoding
  71.  } bdef
  72.  
  73. % Get the metrics of a font, if specified.
  74. /getfontmetrics        % <font-resource> <font> <encoding> getfontmetrics
  75.             %   <font-resource> <font> <encoding> <Metrics|null>
  76.  { 2 index /Widths known
  77.     { 2 dict begin
  78.       /Encoding exch def
  79.       /Metrics Encoding length dict def
  80.       exch
  81.         % Stack: font font-res
  82.         % Note that widths are always based on a 1000-unit
  83.         % character space, but the FontMatrix may specify
  84.         % some other scale factor.  Compensate for this here,
  85.         % by scaling the Widths if necessary.
  86.       0.001 2 index /FontMatrix get 0 get div
  87.         % Stack: font font-res mscale
  88.       1 index /FirstChar oget dup 1 4 index /LastChar oget
  89.        {    % Stack: font font-res mscale first-char index
  90.      Encoding 1 index get
  91.      4 index /Widths oget 2 index 4 index sub get
  92.          % Stack: font font-res mscale first-char index charname width
  93.      4 index mul
  94.         % There is a hack here to deal with encodings where the
  95.         % same character appears more than once, because the Metrics
  96.         % dictionary works by character name, not by character code.
  97.         % Because of this, we can't deal with Width vectors that
  98.         % specify different widths for the same character name
  99.         % appearing multiple times in the Encoding.
  100.      Metrics 2 index .knownget not { 0 } if 0 ne
  101.       { pop pop }
  102.       { Metrics 3 1 roll put }
  103.      ifelse pop
  104.        }
  105.       for pop
  106.         % Now fill in the MissingWidth for any encoded characters
  107.         % that aren't in Metrics already.
  108.         % Stack: font font-res mscale
  109.       Metrics 2 index /FontDescriptor oget
  110.       /MissingWidth knownoget { 2 index mul } { 0 } ifelse exch
  111.       Encoding
  112.        {    % Stack: font font-res mscale missing-width metrics charname
  113.      2 copy known not { 2 copy 4 index put } if pop
  114.        }
  115.       forall pop pop pop
  116.       exch Encoding Metrics end
  117.     }
  118.     { null
  119.     }
  120.    ifelse
  121.  } bdef
  122.  
  123. % ---------------- Descriptors ---------------- %
  124.  
  125. % Partial descriptors for the 14 built-in fonts.
  126. /standardfontdescriptors mark
  127.   /Courier mark /Flags 16#23 .dicttomark
  128.   /Courier-Oblique 1 index
  129.   /Courier-Bold 1 index
  130.   /Courier-BoldOblique 1 index
  131.   /Helvetica mark /Flags 16#20 .dicttomark
  132.   /Helvetica-Oblique 1 index
  133.   /Helvetica-Bold 1 index
  134.   /Helvetica-BoldOblique 1 index
  135.   /Times-Roman mark /Flags 16#22 .dicttomark
  136.   /Times-Bold 1 index
  137.   /Times-Italic mark /Flags 16#62 .dicttomark
  138.   /Times-BoldItalic 1 index
  139.   /Symbol mark /Flags 16#4 .dicttomark
  140.   /ZapfDingbats 1 index
  141. .dicttomark readonly def
  142.  
  143. % ---------------- Utilities ---------------- %
  144.  
  145. % Fabricate a font name by adding %'s on the end.
  146. /genfontname        % <name> genfontname <name>
  147.  { dup length string cvs
  148.     { (%) concatstrings
  149.       dup cvn FontDirectory exch known not { cvn exit } if
  150.     }
  151.    loop
  152.  } bdef
  153.  
  154. % Find a font, and adjust its encoding if necessary.
  155. /pdffindfont        % <font-resource> <fontname> pdffindfont <font>
  156.  { findfont adjustfont
  157.  } bdef
  158.  
  159. % ---------------- Type 1 fonts ---------------- %
  160.  
  161. /buildType1        % <Type1-font-resource> buildType1 <font>
  162.  { dup /BaseFont get pdffindfont
  163.  } bdef
  164.  
  165. % The state dictionary for the embedded Type 1 font reading procedure
  166. % has the following keys and values:
  167. %    data - stream (filter)
  168. %    buffer, buffer2 - string
  169. %    leftstr - string containing (non-negative) integer
  170. %    sectionstr - string containing a character 0 .. 2
  171. %    stream - (stream) dictionary
  172. %    proc - procedure of the form {-dict- type1read}
  173. % When the procedure is executing, this dictionary is current.
  174. % leftstr and sectionstr are strings so that we can change their values
  175. % reliably in case the font executes a restore!
  176.  
  177. % Read an embedded Type 1 font.
  178. /readfontfilter        % <proc> readfontfilter <filter>
  179.  {    % We make this a separate procedure so that we can
  180.     % redefine it when we're writing PostScript.
  181.    0 () /SubFileDecode filter
  182.  } bdef
  183. /readtype1dict 5 dict dup begin
  184.   /definefont {
  185.     dup wcheck not { dup length dict copy } if
  186.     exch pop savedFontName exch
  187.     //systemdict /definefont get exec
  188.   } bdef
  189.   /eexec {
  190.     55665 /eexecDecode filter
  191.     //systemdict begin readtype1dictcopy begin cvx stopped
  192.     currentdict readtype1dictcopy eq { end } if
  193.     currentdict //systemdict eq { end } if
  194.      { stop } if
  195.   } bdef
  196. end readonly def
  197. /readtype1        % <font-resource> <stream-dict> readtype1 <font>
  198.  {        % Read the definition, using a procedure-based filter
  199.         % that turns binary/hex conversion on and off
  200.         % at the right times.
  201.    PDFfile fileposition 3 1 roll
  202.    7 dict begin
  203.      /leftstr (          ) 10 string copy def
  204.        dup /Length1 oget leftstr cvs pop
  205.      /sectionstr <00> 1 string copy def
  206.      /stream 1 index def
  207.      true resolvestream /data exch def
  208.      /buffer 1000 string def        % arbitrary
  209.      /buffer2 buffer length 2.1 div cvi 1 sub string def
  210.    currentdict end
  211.    /type1read cvx 2 array astore cvx dup 0 get /proc 2 index put
  212.    readfontfilter
  213.         % Some buggy embedded fonts leave extra junk on the stack,
  214.         % so we have to make a closure that records the stack depth
  215.         % in a fail-safe way.
  216.    //systemdict begin
  217.         % Rebind definefont so we can substitute the FontName
  218.         % from the descriptor.
  219.    //readtype1dict dup length 2 add dict copy begin
  220.    1 index /FontDescriptor oget /FontName oget /savedFontName exch def
  221.    /readtype1dictcopy currentdict def
  222.     { run } aload pop count 1 sub 2 packedarray cvx exec
  223.    end end
  224.    count exch sub { pop } repeat
  225.    PDFfile 3 -1 roll setfileposition
  226.    /FontDescriptor oget /FontName oget findfont
  227.  } bdef
  228.  
  229. % Execute the appropriate reading procedure.
  230. /type1read        % <dict> type1read <string>
  231.  { begin leftstr cvi
  232.     { type1read1 type1read2 type1read3 } sectionstr 0 get get exec
  233.    (          ) leftstr copy cvs pop end
  234.  } bdef
  235.  
  236. % Read the next block of data into the buffer.
  237. /type1readdata        % <left> <buffer> type1readdata <substring> <left'>
  238.  { 0 2 index 2 index length min getinterval
  239.         % Adobe requires readstring to signal an error if given
  240.         % an empty string.  Work around this nonsense here.
  241.    dup length 0 ne { data exch readstring pop } if
  242.    dup length 3 -1 roll exch sub
  243.    DEBUG
  244.     { dup =only ( read ) print
  245.       1 index length =only (: ) print
  246.       1 index == flush
  247.     } if
  248.  } bdef
  249.  
  250. % Read the next block of the initial text portion.
  251. /type1read1        % <left> type1read1 <string> <left'>
  252.  { DEBUG { (read1 ) print } if
  253.    dup 0 eq
  254.     { pop sectionstr 0 1 put
  255.       stream /Length2 oget type1read2
  256.     }
  257.     { buffer type1readdata
  258.     }
  259.    ifelse
  260.  } bdef
  261.  
  262. % Read the next block of the encrypted portion.
  263. /type1trailer
  264. (0000000000000000000000000000000000000000000000000000000000000000\n\
  265. 0000000000000000000000000000000000000000000000000000000000000000\n\
  266. 0000000000000000000000000000000000000000000000000000000000000000\n\
  267. 0000000000000000000000000000000000000000000000000000000000000000\n\
  268. 0000000000000000000000000000000000000000000000000000000000000000\n\
  269. 0000000000000000000000000000000000000000000000000000000000000000\n\
  270. 0000000000000000000000000000000000000000000000000000000000000000\n\
  271. 0000000000000000000000000000000000000000000000000000000000000000\n\
  272. cleartomark\n)
  273. readonly def
  274. /type1read2        % <left> type1read2 <string> <left'>
  275.  { DEBUG { (read2 ) print } if
  276.    dup 0 eq
  277.     { pop sectionstr 0 2 put
  278.       stream /Length3 oget
  279.       dup 0 eq
  280.        { DEBUG { (trailer ) print } if
  281.      type1trailer exch
  282.        }
  283.        { type1read3
  284.        }
  285.       ifelse
  286.     }
  287.     { buffer2 type1readdata exch
  288.       buffer /ASCIIHexEncode filter dup 3 -1 roll writestring closefile
  289.       buffer (>) search pop exch pop exch pop exch
  290.     }
  291.    ifelse
  292.  } bdef
  293.  
  294. % Read the next block of the final text portion.
  295. % When finished, this procedure returns an empty string.
  296. /type1read3        % <left> type1read3 <string> <left'>
  297.  { DEBUG { (read3 ) print } if
  298.    buffer type1readdata
  299.  } bdef
  300.  
  301. % ---------------- Type 3 fonts ---------------- %
  302.  
  303. /.notdefEncoding 256 { /.notdef } repeat 256 packedarray def
  304.  
  305. /buildType3        % <Type3-font-resource> buildType3 <font>
  306.   { 8 dict begin
  307.     /FontType 3 def
  308.     /FontBBox 1 index /FontBBox get cvx def
  309.     /FontMatrix 1 index /FontMatrix oget def
  310.     /CharProcs 1 index /CharProcs oget def
  311.     /FontName 1 index /Name get genfontname def
  312.     /Encoding .notdefEncoding 2 index getencoding def
  313.     /BuildGlyph
  314.      { exch /CharProcs get exch oget
  315.        PDFfile fileposition exch
  316.        false resolvestream
  317.         % Don't let setgcolor set the color inside the BuildGlyph
  318.         % procedure, because this causes an /undefined error.
  319.        q_ null /FillColor gput null /StrokeColor gput
  320.        pdfopdict .pdfrun
  321.        Q_
  322.        PDFfile exch setfileposition
  323.      } bdef
  324.     FontName currentdict end definefont exch pop
  325.   } bdef
  326.  
  327. % ---------------- TrueType fonts ---------------- %
  328.  
  329. /TTfonts mark
  330.   /Arial /Helvetica
  331.   /Arial,Italic /Helvetica-Oblique
  332.   /Arial,Bold /Helvetica-Bold
  333.   /Arial,BoldItalic /Helvetica-BoldOblique
  334.   /TimesNewRoman /Times-Roman
  335.   /TimesNewRoman,Italic /Times-Italic
  336.   /TimesNewRoman,Bold /Times-Bold
  337.   /TimesNewRoman,BoldItalic /Times-BoldItalic
  338. .dicttomark readonly def
  339.  
  340. /buildTrueType        % <TrueType-font-resource> buildTrueType <font>
  341.  { dup /BaseFont get
  342.    dup TTfonts exch .knownget { exch pop } if pdffindfont
  343.  } bdef
  344.  
  345. % Read an embedded TrueType font.
  346. /readtruetype        % <font-resource> <stream-dict> readtruetype <font>
  347.  {        % This is much simpler than readtype1, because we don't
  348.         % have to deal with the tripartite .PFB format.
  349.    PDFfile fileposition 3 1 roll
  350.    true resolvestream readfontfilter .loadttfont
  351.    dup /FontName get exch definefont exch pop
  352.    PDFfile 3 -1 roll setfileposition
  353.  } bdef
  354.  
  355. % ---------------- Type 0 fonts ---------------- %
  356. %**************** NOT ACTUALLY SUPPORTED YET
  357.  
  358. /buildType0        % <Type0-font-resource> buildType0 <font>
  359. { 10 dict begin
  360.   /FontType 0 def
  361.   /FontMatrix 1 index /FontMatrix knownoget not { matrix } if def
  362.   /FontName 1 index /BaseFont get def
  363.   /FMapType 9 def
  364.   /Encoding [ 0 1 4 index /DescendantFonts oget length 1 sub { } for ] def
  365.   /FDepVector [ 2 index /DescendantFonts oget { exec } forall ] def
  366.   /CMap 1 index /Encoding oget
  367.     dup type /nametype eq
  368.      { dup Page /CMap rget
  369.         { exch pop resolvestream } { /undefined signalerror } ifelse
  370.      }
  371.      { resolvestream
  372.      }
  373.     ifelse
  374.   % FontName currentdict end definefont exch pop
  375.   end pop /Times-Roman findfont
  376. } bdef
  377.  
  378. % ---------------- Other embedded fonts ---------------- %
  379.  
  380. /fontloadprocs mark
  381.   /Type1C /readType1C cvx
  382. .dicttomark readonly def
  383.  
  384. % Read an embedded compressed font.
  385. /readType1C        % <font-resource> <stream-dict> readType1C <font>
  386.  { PDFfile fileposition 3 1 roll
  387.    dup true resolvestream dup readfontfilter
  388.         % Stack: pos resource streamdict stream filter
  389.    3 index /FontDescriptor oget /FontName oget
  390.    1 index FRD
  391.    closefile closefile pop
  392.    PDFfile 3 -1 roll setfileposition
  393.    /FontDescriptor oget /FontName oget findfont
  394.  } bdef
  395.  
  396. % ---------------- Font lookup ---------------- %
  397.  
  398. /fonttypeprocs mark        % <font-resource> -proc- <font>
  399.   /Type0 /buildType0 cvx
  400.   /Type1 /buildType1 cvx
  401.   /MMType1 1 index
  402.   /Type3 /buildType3 cvx
  403.   /TrueType /buildTrueType cvx
  404. .dicttomark readonly def
  405.  
  406. /resourcefont            % <font-resource> resourcefont <font>
  407.  { dup /PSFont .knownget
  408.     { /FID .knownget { type /fonttype eq } { false } ifelse }
  409.     { false }
  410.    ifelse
  411.     { /PSFont get
  412.     }
  413.     { dup dup /FontDescriptor knownoget
  414.        {    % Stack: font-res font-res font-desc
  415.      dup /FontFile knownoget
  416.       { exch pop 1 index 3 1 roll readtype1 adjustfont true }
  417.       { dup /FontFile2 knownoget
  418.          { exch pop 1 index 3 1 roll readtruetype adjustfont true }
  419.          { /FontFile3 knownoget
  420.         { 1 index exch dup /Subtype get fontloadprocs exch get exec adjustfont true }
  421.         { false }
  422.            ifelse
  423.          }
  424.         ifelse
  425.       }
  426.      ifelse
  427.        }
  428.        { false }
  429.       ifelse
  430.         % Stack: font-res font-res false
  431.         %  -or-: font-res font true
  432.       not
  433.        { dup /Subtype get fonttypeprocs exch get exec }
  434.       if
  435.       2 copy /PSFont exch put
  436.       exch pop
  437.     }
  438.    ifelse
  439.  } bdef
  440.  
  441. drawopdict begin
  442.   /d0 /setcharwidth load def
  443.   /d1 /setcachedevice load def
  444.   /Tf
  445.    { exch Page /Resources oget /Font oget exch oget resourcefont
  446.      exch Tf
  447.    } bdef
  448. end
  449.  
  450. end            % pdfdict
  451. end            % GS_PDF_ProcSet
  452. .setglobal
  453.